package com.mjk.common.tools.interceptor;

import java.util.ArrayList;
import java.util.List;

/**
 * 
* @author mjk  
* @date 2019年3月11日
 */
public class DefaultInterceptorChain<Req, Res> implements InterceptorChain<Req, Res> {

    private List<Interceptor<Req, Res>> interceptors;

    public DefaultInterceptorChain() {
    }

    public DefaultInterceptorChain(List<Interceptor<Req, Res>> interceptors) {
        this.interceptors = interceptors;
    }

    public void setInterceptors(List<Interceptor<Req, Res>> interceptors) {
        this.interceptors = interceptors;
    }

    public List<Interceptor<Req, Res>> getInterceptors() {
        return interceptors;
    }
    
    public void addInterceptor(Interceptor<Req, Res> interceptor){
    	if(null == interceptors){
    		this.interceptors = new ArrayList<>();
    	}
    	this.interceptors.add(interceptor);
    }

    public void addInterceptor(int index,Interceptor<Req, Res> interceptor){
    	if(null == interceptors){
    		this.interceptors = new ArrayList<>();
    	}
    	//放到指定位置
    	this.interceptors.add(index,interceptor);
    }
    
    public Res proceed(Req request) {
        RealInterceptorChain<Req, Res> chain = new RealInterceptorChain<>(interceptors, 0);
        return chain.proceed(request);
    }

    static class RealInterceptorChain<Req, Res> extends DefaultInterceptorChain<Req, Res> {

        private final int nextInterceptor;

        private final List<Interceptor<Req, Res>> interceptors;

        public RealInterceptorChain(List<Interceptor<Req, Res>> interceptors, int nextInterceptor) {
            this.interceptors = interceptors;
            this.nextInterceptor = nextInterceptor;
        }

        @Override
        public Res proceed(Req request) {
            if (interceptors == null || nextInterceptor >= interceptors.size()) {
                return null;
            }
            Interceptor<Req, Res> interceptor = this.interceptors.get(nextInterceptor);
            RealInterceptorChain<Req, Res> nextChain = new RealInterceptorChain<>(interceptors, nextInterceptor + 1);
            return interceptor.interceptor(request, nextChain);
        }
    }
}
